#include <opencv2/opencv.hpp>
#include <opencv2/freetype.hpp>
#include <thread>

#include <QGuiApplication>
#include <QImage>
#include <QPainter>
#include <QString>

static void putTextZH(cv::Mat &inMat, const QString text, const cv::Point wordCenter, int inWordSize, const cv::Scalar inColor)
{
    QImage image;
    switch (inMat.type())
    {
    case CV_8UC1:
        image = QImage(inMat.data, inMat.cols, inMat.rows, inMat.cols, QImage::Format_Mono);
        break;
    case CV_8UC3:
        image = QImage(inMat.data, inMat.cols, inMat.rows, inMat.step, QImage::Format_RGB888);
        break;
    case CV_8UC4:
        image = QImage(inMat.data, inMat.cols, inMat.rows, inMat.step, QImage::Format_ARGB32);
        break;
    }
    QColor drawColor(inColor[0], inColor[1], inColor[2]); // 调用时，inColor使用CV_RGB(0, 0, 255)格式颜色
    QPainter painter(&image);
    QPen pen = QPen(drawColor, inWordSize);
    QBrush brush = QBrush(drawColor);
    painter.setPen(pen);
    painter.setBrush(brush);
    QFont font("Source Han Sans", inWordSize);
    painter.setFont(font);
    //painter.drawText(QPoint(wordCenter.x, wordCenter.y), text);
    painter.drawText(QRectF(wordCenter.x, wordCenter.y, inMat.cols-wordCenter.x, inMat.rows-wordCenter.y), Qt::AlignLeft | Qt::AlignTop | Qt::TextWordWrap, text);
}

static void putTextZH(const cv::Mat &inMat, const cv::String text, const cv::Point wordCenter, int inWordSize, const cv::Scalar inColor)
{
    // 创建 FreeType2 对象
    static cv::Ptr<cv::freetype::FreeType2> ft2;
    if (ft2.get() == NULL)
    {
        try
        {
            ft2 = cv::freetype::createFreeType2();
        }
        catch (const cv::Exception &e)
        {
            std::cerr << "Error creating FreeType object: " << e.what() << std::endl;
            return;
        }

        // 加载中文字体文件 (替换为你的字体文件路径)
        std::string fontPath = "/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc"; // Windows 路径示例: "C:/Windows/Fonts/simhei.ttf"
        try
        {
            ft2->loadFontData(fontPath, 0);
        }
        catch (const cv::Exception &e)
        {
            std::cerr << "Error loading font file (" << fontPath << "): " << e.what() << std::endl;
            return;
        }
    }

    int thickness = -1;            // 填充文字
    int lineStyle = cv::LINE_AA;   // 抗锯齿
    bool bottomLeftOrigin = false; // 坐标原点在左上角

    // 绘制中文文本
    try
    {
        ft2->putText(
            inMat,
            text,
            wordCenter,
            inWordSize,
            inColor,
            thickness,
            lineStyle,
            bottomLeftOrigin);
    }
    catch (const cv::Exception &e)
    {
        std::cerr << "Error rendering text: " << e.what() << std::endl;
        return;
    }
    // cv::putText(inMat, text, wordCenter, cv::FONT_HERSHEY_COMPLEX, inWordSize, inColor);
}

int main(int argc, char **argv)
{
    QGuiApplication a(argc, argv);
    char szT[1024];
    time_t tNow;
    cv::Mat frame;
    //--- INITIALIZE VIDEOCAPTURE
    cv::VideoCapture cap;
    // open the default camera using default API
    // cap.open(0);
    // OR advance usage: select any API backend
    int deviceID = 0;        // 0 = open default camera
    int apiID = cv::CAP_ANY; // 0 = autodetect default API
                             // open selected camera using selected API
    cap.open(deviceID);      //, apiID);
    // check if we succeeded
    if (!cap.isOpened())
    {
        std::cerr << "ERROR! Unable to open camera\n"
                  << std::endl;
        return -1;
    }

    cap.set(cv::CAP_PROP_FPS, 30); // 要有这句，否则卡顿
    cv::namedWindow("Live", cv::WINDOW_NORMAL);

    //--- GRAB AND WRITE LOOP
    std::cout << "Start grabbing" << std::endl
              << "Press any key to terminate" << std::endl;
    while (true)
    {
        if (!cap.read(frame))
            break;
        if (frame.empty())
            continue;

        putTextZH(frame, QString::fromLocal8Bit("hello\n你好！"), cv::Point(100, 100), 40, cv::Scalar(0,0,255));
        time(&tNow);
        struct tm *pTM = localtime(&tNow);
        sprintf(szT, "%04d%02d%02d%02d%02d%02d.png", pTM->tm_year + 1900, pTM->tm_mon + 1, pTM->tm_mday, pTM->tm_hour, pTM->tm_min, pTM->tm_sec);
        // cv::imwrite(szT, frame);
        //  do encode
        //  do pkt
        // send(pkt->data, pkt->size);

        cv::imshow("Live", frame);

        // 不加这句，就不能显示画面
        if (cv::waitKey(1) == 27)
            break;

        // std::this_thread::sleep_for(std::chrono::milliseconds(4));
    }

    return a.exec();
}